//UCS CJK code rage:0x4E00 -- 0x9FCF
#include <iostream>
#include <iomanip>
#include <bitset>
#include <fstream>
#include <assert.h>

using namespace std;
typedef unsigned char BYTE;

bool formupUTF8bytes(unsigned int code, BYTE bytes[4], unsigned int & byteusecount)
{

/* utf8 formrole
Char. number range  |        UTF-8 octet sequence                                      | code point number
(hexadecimal)       |              (binary)                                            |
--------------------+-------------------------------------------------------------------------------------
0000 0000-0000 007F | 0xxxxxxx                                                         | 2^7 = 128 
0000 0080-0000 07FF | 110xxxxx 10xxxxxx                                                | 2^11=2k=2048
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx                                       | 2^16=64k=65536
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx                              | 2^21=2m=2097152
*/

	byteusecount = 0;
	unsigned int tmpcode;
	if(code<=0x7F)
	{
		// 0xxxxxxx
		byteusecount=1;
		bytes[0] = BYTE(0x7F&code);
	}
	else if(code<=0x7FF)
	{
		//110xxxxx 10xxxxxx
		byteusecount=2;
		bytes[1] = BYTE(0x3F&code);
		bytes[1] |= 0x80;

		tmpcode = 0x7C0&code;
		tmpcode >>= 6;
		bytes[0] = BYTE(tmpcode);
		bytes[0] |= 0xC0;
	}
	else if(code<=0xFFFF)
	{
		//1110xxxx 10xxxxxx 10xxxxxx
		//9fcf : 00000000000000001001111111001111 : 11101001 - 10111111 - 10001111
		byteusecount=3;
		bytes[2] = BYTE(0x3F&code);
		bytes[2] |= 0x80;

		tmpcode = 0xFC0&code;
		tmpcode >>= 6;
		bytes[1] = BYTE(tmpcode);
		bytes[1] |= 0x80;
		
		tmpcode = 0x3F000&code;
		tmpcode >>= 12;
		bytes[0] = BYTE(tmpcode);
		bytes[0] |= 0xE0;
	}
	else if(code<=0x10FFFF)
	{
		byteusecount=4;
		bytes[3] = BYTE(0x3F&code);
		bytes[3] |= 0x80;

		tmpcode = 0xFC0&code;
		tmpcode >>= 6;
		bytes[2] = BYTE(tmpcode);
		bytes[2] |= 0x80;

		tmpcode = 0x3F000&code;
		tmpcode >>= 12;
		bytes[1] = BYTE(tmpcode);
		bytes[1] |= 0x80;

		tmpcode = 0x1C0000&code;
		bytes[0] = BYTE(tmpcode);
		bytes[0] |= 0xF0;
	}
	else
	{
		return false;
	}
	return true;
}

int main()
{
	BYTE utf8bytes[4];
	unsigned int byteuse;
	unsigned int code;

	ofstream fout("cjk_utf8_CodeTable");
	for(code=0x4E00; code <= 0x9FCF; ++code)
	{
		cout<<setbase(16)<<code<<" : "<<bitset<sizeof(unsigned int)*8>(code)<<" : ";
		if(formupUTF8bytes(code, utf8bytes, byteuse))
		{
			for(unsigned int j=0;j<byteuse;++j)
			{
				cout<<bitset<sizeof(BYTE)*8>(utf8bytes[j]);
				if(1 < (byteuse-j))
				{
					cout<<" - ";
				}
				else
				{
					cout<<endl;
				}
			}
		}
		else
		{
			cout<<"fail to formup as UTF8"<<endl;
		}
	}
	fout.close();
	return 0;
}
